<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>running-man game</title>
</head>
<body>
  <canvas id="demoCanvas" width="960" height="400"></canvas>
  
  <script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
  <script>
    window.onload = () => {
      let stage, w, h, loader;
      let sky, grant, ground, hill, hill2;

      function init() {
        stage = new createjs.StageGL("demoCanvas");

        // 获取画布的宽和高，后面计算使用
        w = stage.canvas.width;     // 960
        h = stage.canvas.height;    // 400

        // 定义静态资源
        let manifest = [{
          src: "spritesheet_grant.png", id: "grant"}, {     // 人物动作雪碧图
          src: "sky.png", id: "sky"}, {           // 天空
          src: "ground.png", id: "ground"}, {     // 地面
          src: "hill1.png", id: "hill"}, {        // 远山
          src: "hill2.png", id: "hill2"           // 近山
        }];     // Array, String, Object
        
        // 创建资源加载队列
        // (Boolean) 用XHR还是用HTML标签来加载
        // 如果是false的时候，就用标签来加载，如果不能用标签的话，就用XHR来加载。默认是true，用XHR来加载。
        loader = new createjs.LoadQueue(false);
        // 添加"资源加载完成"事件
        loader.addEventListener("complete", handleComplete);
        // 加载资源
        loader.loadManifest(manifest, true, "./assets/img/");  // (manifest, loadNow, basePath)
      }

      /**
       * 静态资源加载完成，处理函数
       */
      function handleComplete() {
        // 渲染天空
        sky = new createjs.Shape();
        sky.graphics.beginBitmapFill(loader.getResult("sky")).drawRect(0, 0, w, h);
        // 定义缓存区域(整个天空的区域))
        sky.cache(0, 0, w, h);

        // 渲染地面
        let groundImg = loader.getResult("ground");
        ground = new createjs.Shape();
        // 注意：drawRect()宽度要躲绘制一个单位
        ground.graphics.beginBitmapFill(groundImg).drawRect(0, 0, w + groundImg.width, groundImg.height);
        ground.tileW = groundImg.width;
        ground.y = h - groundImg.height;
        // 缓存区域(地面的区域)
        ground.cache(0, 0, w + groundImg.width, groundImg.height);

        // 随机渲染远处山脉
        hill = new createjs.Bitmap(loader.getResult("hill"));
        // 设置图像转换
        // setTransform([x=0], [y=0], [scaleX=1], [scaleY=1], [rotation=0], [skewX=0], [skewY=0], [regX=0], [regY=0])
        hill.setTransform(Math.random() * w, h - hill.image.height * 4 - groundImg.height, 4, 4);
        hill.alpha = 0.5;     // 设置透明度

        // 随机渲染近处山脉
        hill2 = new createjs.Bitmap(loader.getResult("hill2"));
        hill2.setTransform(Math.random() * w, h - hill2.image.height * 3 - groundImg.height, 3, 3);

        // 创建雪碧图动画
        let spriteSheet = new createjs.SpriteSheet({
          framerate: 30,      // 帧率 FPS
          "images": [loader.getResult("grant")],      // 雪碧图原图
          "frames": {"width": 165, "height": 292, "count": 64, "regX": 82, "regY": 0},  // 初始化
          // 定义动画
          "animations": {
            "run": [0, 25, "run"],     // name: [开始索引, 结束索引, '下一个动画名称', 倍率]
            "jump": [26, 63, "run"]
          }
        });

        // 绘制动画
        grant = new createjs.Sprite(spriteSheet, "run");
        // 处理雪碧图人物下方空白
        grant.y = 35;

        // 将生成的所有内容渲染至舞台
        stage.addChild(sky, ground, hill, hill2, grant);

        // 监听舞台上的鼠标点击事件
        stage.addEventListener("stagemousedown", () => {
          // 跳转播放 jump 动画
          grant.gotoAndPlay("jump");
        });

        createjs.Ticker.timingMode = createjs.Ticker.RAF;     // RAF / RAF_SYNCHED / TIMEOUT
        createjs.Ticker.addEventListener("tick", tick);

      }


      /**
       * 定时器-重绘舞台
       */
      function tick(event) {
        // event.delta -- 上一次tick到当前tick的ms
        let deltaS = event.delta / 1000;
        // 雪碧图人物移动距离
        let position = grant.x + 150 * deltaS;

        // getBounds() -- 返回当前帧相对于雪碧图原点的边界
        let grantW = grant.getBounds().width * grant.scaleX;
        grant.x = (position >= w + grantW) ? -grantW : position;

        ground.x = (ground.x - deltaS * 150) % ground.tileW;

        // 从右至左移动山脉
        hill.x = (hill.x - deltaS * 30);
        // 如果山脉从左侧离开屏幕
        if (hill.x + hill.image.width * hill.scaleX <= 0) {
          hill.x = w;     // 重置回屏幕最右侧
        }

        // 处理如上
        hill2.x = (hill2.x - deltaS * 45);
        if (hill2.x + hill2.image.width * hill2.scaleX <= 0) {
          hill2.x = w;
        }

        stage.update();
      }

      // 程序主入口-初始化
      init()
    }
  </script>
</body>
</html>